/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package poker.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;


/**
 * Plays one round.
 * 
 * 
 * @author Benjamin L. Brodie <blbrodie@gmail.com>
 */
public class Game {
    static List<Card> deck;
    
    private List<Card> shuffledDeck;
    private Random random = new Random();
    private Player p1;
    private Player p2;
    private List<Card> flopCards;
    private TexasHand flopHand;
    private boolean preFlop = true;
      
    
    public Game(Player playerA, Player playerB){
        
        if (random.nextBoolean()){
            p1 = playerA;
            p2 = playerB;
        } else{
            p2 = playerA;
            p1 = playerB;
        }
        
        
        flopCards = new ArrayList<Card>();
        flopHand = new TexasHand(flopCards);
        
        if (deck == null){
            deck = generateDeck();
        }
        
        shuffledDeck = new ArrayList<Card>(deck);
        Collections.shuffle(shuffledDeck);
        
        p1.setPocketCards(shuffledDeck.remove(0), shuffledDeck.remove(0));
        p2.setPocketCards(shuffledDeck.remove(0), shuffledDeck.remove(0));
        
     
        
        
    }

    
    public static List<Card> generateDeck(){
       // System.out.println("generated deck");
        List<Card> d = new ArrayList<Card>();
        
        for (int value = 2; value < 15; value++){
            for (int suite = 1; suite < 5; suite++){
                d.add(new Card(value,suite));
            }
        }
        
        return d;
    }
    
    public void play(){
        p1.updateCurrentChips(10);
        p2.updateCurrentChips(20);
        
        boolean fold = false;
        int level = 0;
        for(int round = 0; round < 4 && !fold; round++){
            
            assert round < 5 && !fold;
            
            if (round == 1){
                flopCards.add(shuffledDeck.remove(0));
                flopCards.add(shuffledDeck.remove(0));
                flopCards.add(shuffledDeck.remove(0));
                flopHand = new TexasHand(flopCards);
                assert flopCards.size() == 3;
            }
            else if (round == 2){
                flopCards.add(shuffledDeck.remove(0));
                flopHand = new TexasHand(flopCards);
                assert flopCards.size() == 4;
            }
            else if (round == 3){
                flopCards.add(shuffledDeck.remove(0));
                flopHand = new TexasHand(flopCards);
                assert flopCards.size() == 5;
            }
            
            
            
            assert level == 0: "Level is wrong!";
           
        
            //after the first round, not preFlop
            if (round > 0){
                preFlop = false;
            } 
            else 
                preFlop = true;
            
             assert (round == 0 && preFlop) || (round > 0 && !preFlop);
        
            fold = playRound(p1,p2,level);
 
        }
        
        endGame(p1, p2);
        
        
        
    }
    
    /**
     * Compares player hands and updates winnings accordingly.
     * 
     * @param p1 
     * @param p2 
     */
    private void endGame(Player p1, Player p2){
        List<Card> p1cards = new ArrayList<Card>();
        List<Card> p2cards = new ArrayList<Card>();
        
        p1cards.addAll(flopCards);
        p2cards.addAll(flopCards);
        p1cards.addAll(p1.getPocket().getHand());
        p2cards.addAll(p2.getPocket().getHand());
        
        
        TexasHand p1Hand = new TexasHand(p1cards);
        TexasHand p2Hand = new TexasHand(p2cards);
        
        if (p1Hand.compareTo(p2Hand) > 0){
            p1.addToTotalChipsWon(p2.getCurrentChips());
            p2.addToTotalChipsWon(-p2.getCurrentChips());
        }
        else if (p1Hand.compareTo(p2Hand) < 0){
            p2.addToTotalChipsWon(p1.getCurrentChips());
            p1.addToTotalChipsWon(-p1.getCurrentChips());
        }
        
        else{
            int total = p2.getCurrentChips() + p1.getCurrentChips();
            p1.addToTotalChipsWon((total/2) - p1.getCurrentChips());
            p2.addToTotalChipsWon((total/2) - p2.getCurrentChips());
        }
        
    }
    
    private boolean playRound(
            Player player, 
            Player opponent,
            int level){
        
        Move move = player.nextMove(level, player.getCurrentChips(), 
                                 opponent.getCurrentChips(), preFlop, flopHand);
        
        //System.out.println(level + ". " + move);
        
        if (move == Move.FOLD){
            
//            System.out.print(": " + "Player chips: " + player.getCurrentChips() +
//                             ", Opponent Chips: " + opponent.getCurrentChips());
            
            return true;
        }
        
        else if (move == Move.CALL){
            
            if (level != 0){
                
                player.updateCurrentChips(opponent.getCurrentChips());
                return false;
            }
            else{
                assert opponent.getCurrentChips() == player.getCurrentChips() + 20 ||
                       opponent.getCurrentChips() == player.getCurrentChips() + 10:
                        "Player chips are not opponents chips - 20";
                
                player.updateCurrentChips(opponent.getCurrentChips()); //set them equal
                
//                System.out.print(": " + "Player chips: " + player.getCurrentChips() +
//                             ", Opponent Chips: " + opponent.getCurrentChips());
//                
                
                return playRound(opponent, player, level +1);
            }
            
        }
        
        else if (move == Move.CHECK){
            
            assert opponent.getCurrentChips() == player.getCurrentChips();
            
//            System.out.print(": " + "Player chips: " + player.getCurrentChips() +
//                             ", Opponent Chips: " + opponent.getCurrentChips());
            
            if (level != 0){
                return false;
            }
            else{
                return playRound(opponent, player, level +1);
            }
            
        }
        
        else{ //move == move.RAISE;
            
            assert move == Move.RAISE: "else is hit, but move isn't Raise!";
            
            assert opponent.getCurrentChips() == player.getCurrentChips() + 20 ||
                   opponent.getCurrentChips() == player.getCurrentChips() + 10 ||
                   opponent.getCurrentChips() == player.getCurrentChips() && level == 0:
                   "Player chips: " + player.getCurrentChips() +
                   ", Opponent chips: " + opponent.getCurrentChips();
            
            player.updateCurrentChips(opponent.getCurrentChips() + 20); //players chips are 20 + opponent's
//            
//            System.out.print(": " + "Player chips: " + player.getCurrentChips() +
//                             ", Opponent Chips: " + opponent.getCurrentChips());
            
            assert player.getCurrentChips() == opponent.getCurrentChips() + 20:
                    "Player chips are not 20 + opponent's chips";
            
            return playRound(opponent, player, level +1);
        
        }
    }

}
